package com.chuangshu.chuangshuteam.aspect;

import com.chuangshu.chuangshuteam.annotation.RequiresPermissions;
import com.chuangshu.chuangshuteam.annotation.RequiresRoles;
import com.chuangshu.chuangshuteam.annotation.RequiresDirection;
import com.chuangshu.chuangshuteam.config.BaseContext;
import com.chuangshu.chuangshuteam.service.AuthService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * 权限控制切面
 */
@Slf4j
@Aspect
@Component
public class PermissionAspect {

    @Autowired
    private AuthService authService;

    /**
     * 权限控制切面
     */
    @Around("@annotation(requiresPermissions)")
    public Object checkPermission(ProceedingJoinPoint joinPoint, RequiresPermissions requiresPermissions) throws Throwable {
        Long userId = BaseContext.getCurrentId();
        if (userId == null) {
            throw new SecurityException("用户未登录");
        }

        String[] permissions = requiresPermissions.value();
        boolean hasPermission = checkPermissions(userId, permissions, requiresPermissions.logical());

        if (!hasPermission) {
            throw new SecurityException("权限不足");
        }

        return joinPoint.proceed();
    }

    /**
     * 角色控制切面
     */
    @Around("@annotation(requiresRoles)")
    public Object checkRole(ProceedingJoinPoint joinPoint, RequiresRoles requiresRoles) throws Throwable {
        Long userId = BaseContext.getCurrentId();
        if (userId == null) {
            throw new SecurityException("用户未登录");
        }

        String[] roles = requiresRoles.value();
        boolean hasRole = checkRoles(userId, roles, requiresRoles.logical());

        if (!hasRole) {
            throw new SecurityException("角色权限不足");
        }

        return joinPoint.proceed();
    }

    /**
     * 方向权限控制切面
     */
    @Around("@annotation(requiresDirection)")
    public Object checkDirection(ProceedingJoinPoint joinPoint, RequiresDirection requiresDirection) throws Throwable {
        Long userId = BaseContext.getCurrentId();
        if (userId == null) {
            throw new SecurityException("用户未登录");
        }

        // 获取方向参数值
        String direction = getDirectionParam(joinPoint, requiresDirection.param());
        if (direction == null) {
            throw new IllegalArgumentException("方向参数不能为空");
        }

        if (!authService.hasDirectionPermission(userId, direction)) {
            throw new SecurityException("无权限访问该方向数据");
        }

        return joinPoint.proceed();
    }

    private boolean checkPermissions(Long userId, String[] permissions, RequiresPermissions.Logical logical) {
        if (logical == RequiresPermissions.Logical.AND) {
            for (String permission : permissions) {
                if (!authService.hasPermission(userId, permission)) {
                    return false;
                }
            }
            return true;
        } else {
            for (String permission : permissions) {
                if (authService.hasPermission(userId, permission)) {
                    return true;
                }
            }
            return false;
        }
    }

    private boolean checkRoles(Long userId, String[] roles, RequiresPermissions.Logical logical) {
        if (logical == RequiresPermissions.Logical.AND) {
            for (String role : roles) {
                if (!authService.hasRole(userId, role)) {
                    return false;
                }
            }
            return true;
        } else {
            for (String role : roles) {
                if (authService.hasRole(userId, role)) {
                    return true;
                }
            }
            return false;
        }
    }


    private String getDirectionParam(ProceedingJoinPoint joinPoint, String paramName) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Parameter[] parameters = method.getParameters();
        Object[] args = joinPoint.getArgs();

        for (int i = 0; i < parameters.length; i++) {
            if (paramName.equals(parameters[i].getName())) {
                return args[i] != null ? args[i].toString() : null;
            }
        }

        // 如果参数名不匹配，尝试从请求参数中获取
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            return attributes.getRequest().getParameter(paramName);
        }

        return null;
    }
}